const uploadPath = "/slime/fileupload";
const fileUploadPath = @path(@kitty().mewchan.documentPath, @options("uploadPath") || "files");
if (!@.fs.isUnderDir(@kitty().mewchan.documentPath, fileUploadPath)) {
    @warn("Slime file upload is only valid under mewchan document path");
    module.exports = function(lab) {
        return {}
    }
}

/*@lab(function(lab) {
    if (lab.redis.sessionManager) {
        @servlet.session(uploadPath, lab.redis.sessionManager);
    } else {
        @servlet.session(uploadPath);
    }
})*/


var copyFileToUploadFolder = function({lab, filePrefix, dirPath, file, name, cdn, overwrite}) {
    let fileName = name ? name : @.fs.basename(file);
    let fileExtName = @.fs.extname(fileName) || "";
    
    let filePath = @.fs.realOSPath(fileUploadPath, dirPath, fileName);

    return @.async(function() {

        if (@.fs.exists(filePath)) {

            if (overwrite) {
                @.fs.writeFile(filePath, @.fs.readFile.sync(file)).pipe(this);
            } else {
                filePath = @.fs.realOSPath(fileUploadPath, dirPath, @.fs.basename(fileName) + "." + @.fs.hash.md5.sync(file) + fileExtName);
                if (@.fs.exists.file(filePath)) {
                    this.next();
                } else {
                    @.fs.copyFile(file, filePath).pipe(this);
                }
            }

        } else {
            @.fs.copyFile(file, filePath).pipe(this);
        }

    }).then(function() {
        
        if (cdn) {

            if (lab.uploader[cdn]) {

                return lab.uploader[cdn].@uploadFile(filePath).then(function(fileURL) {
                    this.next({
                        fileName, 
                        filePath : filePrefix + "/" + @.fs.filename(filePath),
                        fileURL
                    })
                })

            } else {
                throw @lab.errors.not_support;
            }

        } else {
            this.next({
                fileName, 
                filePath : filePrefix + "/" + @.fs.filename(filePath)
            });
        }
    })
}

@servlet.post(uploadPath, function(request, response) {

    this.break();
    return request.normalize().then(function() {
        var fileNames = [];
        var fileURLs = {};
        var filePaths = {};
        var filePrefix = @options("uploadPrefix") || "files/";

        @lab(function(lab) {

            return @.async(function() {

                let date = @.format.date(new Date(), 'YYYYMMDD');

                if (request.form.id) {

                    lab.find("slime_file_upload_tokens", request.form.id).then(function(token) {
                        if (token && !token.finished) {
                            if (token.uid) {

                                filePrefix += `${token.uid}/${date}`
                                dirPath = @.fs.realOSPath(fileUploadPath, token.uid, date);

                            } else if (token.member_id) {

                                filePrefix += `${token.member_id}/${date}`
                                dirPath = @.fs.realOSPath(fileUploadPath, token.member_id, date);

                            } else if (request.session.currentUser || request.session.currentMember) {

                                if (request.session.currentUser) {
                                    filePrefix += `${request.session.currentUser.id}/${date}`
                                    dirPath = @.fs.realOSPath(fileUploadPath, request.session.currentUser.id, date);
                                } else {
                                    filePrefix += `${request.session.currentMember.id}/${date}`
                                    dirPath = @.fs.realOSPath(fileUploadPath, request.session.currentMember.id, date);
                                }

                            } else {
                                filePrefix += `tmp-user/${date}`
                                dirPath = @.fs.realOSPath(fileUploadPath, "tmp-user", date);
                            }

                            if (!@.fs.exists.dir(dirPath)) {
                                @.fs.makeDirs([dirPath])
                            }

                            this.next(dirPath, token);
                        } else {
                            this.reject(@.error.http(404));
                        }
                    }).pipe(this);

                } else if (request.session.currentUser || request.session.currentMember) {

                    if (request.session.currentUser) {
                        filePrefix += `${request.session.currentUser.id}/${date}`
                        dirPath = @.fs.realOSPath(fileUploadPath, request.session.currentUser.id, date);
                    } else {
                        filePrefix += `${request.session.currentMember.id}/${date}`
                        dirPath = @.fs.realOSPath(fileUploadPath, request.session.currentMember.id, date);
                    }

                    if (!@.fs.exists.dir(dirPath)) {
                        @.fs.makeDirs([dirPath])
                    }

                    this.next(dirPath);
                } else {
                    this.reject(@.error.http(403));
                }

            }).then(function(difilePathsth, uploadToken) {

                let files = request.files;

                return @.async.all(files, function({ file, name }) {
                    // 保存的文件名

                    copyFileToUploadFolder({lab, filePrefix, dirPath, file, name, cdn : request.form.cdn, overwrite : request.form.overwrite}).then(async function ({fileName, filePath, fileURL}) {

                        fileNames.push(fileName);
                        filePaths[fileName] = filePath;
                        fileURLs[fileName] = fileURL;

                    }).pipe(this);

                }).then(function() {
                    var uploadResult = {
                        fileNames: fileNames,
                        fileURLs: fileURLs,
                        filePaths: filePaths
                    }
                    if (uploadToken) {
                        lab.update("slime_file_upload_tokens", uploadToken, {
                            upload_date: Date.now(),
                            finished: true,
                            result: uploadResult
                        }).pipe(this);
                    } else {
                        lab.create("slime_file_upload_tokens", {
                            uid: request.session.currentUser ? request.session.currentUser.id : undefined,
                            member_id: request.session.currentMember ? request.session.currentMember.id : undefined,
                            create_date: Date.now(),
                            finished: true,
                            upload_date: Date.now(),
                            result: uploadResult
                        }).pipe(this);
                    }
                });
            })
        }).finished((error, uploadToken) => {

            if (error) {

                @error(error);
                response.send({
                    error: error.message
                }).pipe(this);

            } else {

                response.send(uploadToken.result).pipe(this);

            }
        })
    });

});

module.exports = function(lab) {
    return {
        requestUploadToken: function(session) {

            if (!(session.currentUser || session.currentMember)) {
                throw @lab.errors.not_login;
            }

            return lab.slime.core.@requestUploadToken({
                uid: session.currentUser ? session.currentUser.id : undefined,
                member_id: session.currentMember ? session.currentMember.id : undefined,
            });
        },
        @requestUploadToken: function({ uid, member_id }) {
            return lab.create("slime_file_upload_tokens", {
                uid,
                member_id,
                create_date: Date.now()
            }).then(function({ id }) {
                this.next(id);
            });
        },
        @sendLocalFileToUploadPath: function({ member_id, uid, filePath }) {

            if (@.fs.exists(filePath)) {

                let date = @.format.date(new Date(), 'YYYYMMDD');
                var filePrefix = @options("uploadPrefix") || "files/";
                
                if (uid) {

                    filePrefix += `${uid}/${date}`
                    dirPath = @.fs.realOSPath(fileUploadPath, uid, date);

                } else if (member_id) {

                    filePrefix += `${member_id}/${date}`
                    dirPath = @.fs.realOSPath(fileUploadPath, uid, date);

                } else {
                    filePrefix += `tmp-user/${date}`
                    dirPath = @.fs.realOSPath(fileUploadPath, request.session.currentMember.id, date);
                }

                if (!@.fs.exists.dir(dirPath)) {
                    @.fs.makeDirs([dirPath])
                }
                
                return copyFileToUploadFolder({lab, filePrefix, dirPath, file : filePath });
            } else {
                throw @lab.errors.object_not_found;
            }
        }
    }
}